//    Academic project for DOS, sorts numbers concurrently on 5 machines
//    Copyright (C) 2010  PRITHVI RAJ VENKAT RAJ
//
//       Licensed to the Apache Software Foundation (ASF) under one
//       or more contributor license agreements.  See the NOTICE file
//       distributed with this work for additional information
//       regarding copyright ownership.  The ASF licenses this file
//       to you under the Apache License, Version 2.0 (the
//       "License"); you may not use this file except in compliance
//       with the License.  You may obtain a copy of the License at
//
//         http://www.apache.org/licenses/LICENSE-2.0
//
//       Unless required by applicable law or agreed to in writing,
//       software distributed under the License is distributed on an
//       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//       KIND, either express or implied.  See the License for the
//       specific language governing permissions and limitations
//       under the License.


import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Hashtable;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;


public class Connection implements Runnable{
	public static int cpu=0;	
	private Socket client = null;
	private ObjectInputStream ois = null;
	private ObjectOutputStream oos = null;
	private SerializedObject x = null;
	static int[][] assigned=new int[20][20];
	static int p=0;
//	int dataset1[] = {0, 0, 0, 0, 0, 0, 0};
	static Boolean  work=true;
	//Connection ab=new Connection();
	static CyclicBarrier barrier=new CyclicBarrier(5);
	static boolean parr[]={false,false,false,false,false};
	static boolean sorted[]={false,false,false,false,false};
	String client_id="";
	static Hashtable<String, Integer> client_table =new Hashtable<String, Integer>();
	
	public Connection() {}
	
    public  Connection(Socket clientSocket) {
	    //barrier=
    	 client = clientSocket;
         cpu=0;
         Thread t=new Thread (this);
         t.start();
	    // this.start();
	     
	   }
    public void inits(){
    //System.out.println("NAME IS  (inits)"+t.getId());
    }
    
    
  //  private synchronized void incrp(){p++;}
    
    private synchronized int selectp(){
    for(int i=0;i<5;i++)
    {
    	if(!parr[i]){
    	parr[i]=true;
    	return i;	
    	}
    	
    }
    	return -1;
    	
    }
    
    public Boolean verifyThreads(){
    		
    	if(parr[0]&&parr[1]&&parr[2]&&parr[3]&&parr[4]) return false;
    	return true;
    }
    
    public  void transfer() throws Exception{
    	int p=selectp();
       //p=client_table.get(client_id);
    	//String temp=client_id[2];
//    	System.out.println(client_id.substring(2, 3)+"  "+client_id.substring(1, 2));
    	p= Integer.parseInt(client_id.substring(2, 3))-1;
//    	System.out.println()
//    	System.out.println("ClientHandler: current p is"+p+"and cpu is"+cpu+"client_id"+client_id);
//    	for(int i=0;i<assigned[p].length;i++) 
//    	System.out.print(assigned[p][i]+"  ");
        
    	Thread.sleep(500);
    	barrier.await();
    	System.out.println("Client Handler: Sent Array data ("+assigned[p].length+") to client ["+client_id+"]");
        
    	// ship the object to the client
        SerializedObject output = new SerializedObject();
        output.setArray(assigned[p]);
        oos.writeObject(output);
        oos.flush();
        
        
        //get object from client
        x = (SerializedObject) ois.readObject();
        assigned[p] = x.getArray();
        sorted[p]=true;
        System.out.println(" ");
      System.out.print("ClientHandler: Client "+x.getClient_id()+"	Sorted   :" ); 
      //print sorted array
      System.out.print("{");
      for(int i=0;i<assigned[p].length;i++) 
      System.out.print(assigned[p][i]+",");
      System.out.print("}");
      
        
        
        // cleanup
        ois.close();
        oos.close();
        client.close(); 
        
    	}
    
    
    
    public void run() {
    	 try {
	      ois = new ObjectInputStream(client.getInputStream());
	      oos = new ObjectOutputStream(client.getOutputStream());
	      x=(SerializedObject) ois.readObject();
	      cpu=x.getCpu();
	      client_id=x.getClient_id();
	      
	      System.out.println("Client Handler:Got CPU as :"+cpu+" from Client ["+client_id+"]");
	      client_table.put(client_id, new Integer(cpu));
	     } catch(Exception e1) {
	         try {
	            client.close();
	         }catch(Exception e) {
	           System.out.println(e.getMessage());
	         }
	       
	     } 

	     try { 
    		
    		System.out.println("Connection Handler:Waiting for synch(5) :"+(1+barrier.getNumberWaiting())+" reached");
    		barrier.await();
    		
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (BrokenBarrierException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
 	    try {
           
 	    	transfer();
            
 
        } catch(Exception e) {e.printStackTrace();}       
     
    }
	
    
    public synchronized int[][] getArray(){
//    while(!(sorted[0]&&sorted[1]&&sorted[2]&&sorted[3]&&sorted[4])){
    //	System.out.println(sorted[0]+" "+sorted[1]+" "+sorted[2]+" "+sorted[3]+" "+sorted[4]);
    	
//    }
    return assigned;
    }
    
    public  void setArray(int[][] array){assigned=array;work=false;System.out.println("Client Handler:Data assigned");
    
   
    //System.out.println("in connection class setarray");
//    for(int p=0;p<5;p++) 
//	{for(int k=0;k<assigned[p].length;k++)  
//	  System.out.print(assigned[p][k]+"   "); 
//	System.out.println(" ");
//	}
//    
    
    }
    
    public Hashtable<String, Integer> getHashtable(){ return client_table;} 
    public int getCpu(){
    	try{
        //read cpu

    	}
    	catch(Exception e){ System.out.println(e.getMessage());}
    	return cpu;
    	}
    
    
    

	
}
